columview: Fix column resizing
authorMatthias Clasen <mclasen@redhat.com>
Thu, 24 Sep 2020 18:18:38 +0000 (14:18 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Thu, 24 Sep 2020 18:18:38 +0000 (14:18 -0400)
We were not handling the fixed_width quite right,
and that was causing screaming from the GTK size
allocation machinery.

Fixes: #3178
gtk/gtkcolumnviewcell.c
gtk/gtkcolumnviewlayout.c
gtk/gtkcolumnviewtitle.c

index ace803718805b7832ee771b0eb520b812f4c82c0..0881a6ccd3974a374532f95bd4fc3b58bc6d94bc 100644 (file)
@@ -25,6 +25,9 @@
 #include "gtkintl.h"
 #include "gtklistitemwidgetprivate.h"
 #include "gtkwidgetprivate.h"
+#include "gtkcssnodeprivate.h"
+#include "gtkcssnumbervalueprivate.h"
+
 
 struct _GtkColumnViewCell
 {
@@ -44,6 +47,37 @@ struct _GtkColumnViewCellClass
 
 G_DEFINE_TYPE (GtkColumnViewCell, gtk_column_view_cell, GTK_TYPE_LIST_ITEM_WIDGET)
 
+static int
+get_number (GtkCssValue *value)
+{
+  double d = _gtk_css_number_value_get (value, 100);
+
+  if (d < 1)
+    return ceil (d);
+  else
+    return floor (d);
+}
+
+static int
+unadjust_width (GtkWidget *widget,
+                int        width)
+{
+  GtkCssStyle *style;
+  int widget_margins;
+  int css_extra;
+
+  style = gtk_css_node_get_style (gtk_widget_get_css_node (widget));
+  css_extra = get_number (style->size->margin_left) +
+              get_number (style->size->margin_right) +
+              get_number (style->border->border_left_width) +
+              get_number (style->border->border_right_width) +
+              get_number (style->size->padding_left) +
+              get_number (style->size->padding_right);
+  widget_margins = widget->priv->margin.left + widget->priv->margin.right;
+
+  return MAX (0, width - widget_margins - css_extra);
+}
+
 static void
 gtk_column_view_cell_measure (GtkWidget      *widget,
                               GtkOrientation  orientation,
@@ -56,15 +90,18 @@ gtk_column_view_cell_measure (GtkWidget      *widget,
   GtkColumnViewCell *cell = GTK_COLUMN_VIEW_CELL (widget);
   GtkWidget *child = gtk_widget_get_first_child (widget);
   int fixed_width = gtk_column_view_column_get_fixed_width (cell->column);
+  int unadj_width;
+
+  unadj_width = unadjust_width (widget, fixed_width);
 
   if (orientation == GTK_ORIENTATION_VERTICAL)
     {
       if (fixed_width > -1)
         {
           if (for_size == -1)
-            for_size = fixed_width;
+            for_size = unadj_width;
           else
-            for_size = MIN (for_size, fixed_width);
+            for_size = MIN (for_size, unadj_width);
         }
     }
 
@@ -74,7 +111,10 @@ gtk_column_view_cell_measure (GtkWidget      *widget,
   if (orientation == GTK_ORIENTATION_HORIZONTAL)
     {
       if (fixed_width > -1)
-        *minimum = *natural = fixed_width;
+        {
+          *minimum = 0;
+          *natural = unadj_width;
+        }
     }
 }
 
@@ -84,10 +124,16 @@ gtk_column_view_cell_size_allocate (GtkWidget *widget,
                                     int        height,
                                     int        baseline)
 {
+  GtkColumnViewCell *self = GTK_COLUMN_VIEW_CELL (widget);
   GtkWidget *child = gtk_widget_get_first_child (widget);
 
   if (child)
-    gtk_widget_allocate (child, width, height, baseline, NULL);
+    {
+      if (gtk_column_view_column_get_fixed_width (self->column) > -1)
+        gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, height, NULL, &width, NULL, NULL);
+
+      gtk_widget_allocate (child, width, height, baseline, NULL);
+    }
 }
 
 static void
index 1b56a3b6ff822df3ed16d7c1387bce1f4ce5d5d8..6f9dfdb13c52787c05111031d91a8c7835b1a483 100644 (file)
@@ -128,7 +128,7 @@ gtk_column_view_layout_allocate (GtkLayoutManager *layout_manager,
        child = _gtk_widget_get_next_sibling (child))
     {
       GtkColumnViewColumn *column;
-      int col_x, col_width;
+      int col_x, col_width, min;
 
       if (!gtk_widget_should_layout (child))
         continue;
@@ -144,7 +144,9 @@ gtk_column_view_layout_allocate (GtkLayoutManager *layout_manager,
           gtk_column_view_column_get_header_allocation (column, &col_x, &col_width);
         }
 
-      gtk_widget_size_allocate (child, &(GtkAllocation) { col_x, 0, col_width, height }, baseline);
+      gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, -1, &min, NULL, NULL, NULL);
+
+      gtk_widget_size_allocate (child, &(GtkAllocation) { col_x, 0, MAX (min, col_width), height }, baseline);
     }
 }
 
index 12c39d9ba3ca24756b98715466fc55704cdffb92..bc06da1670312cb123005f024955f50de8a6491f 100644 (file)
@@ -32,6 +32,8 @@
 #include "gtkgestureclick.h"
 #include "gtkpopovermenu.h"
 #include "gtknative.h"
+#include "gtkcssnodeprivate.h"
+#include "gtkcssnumbervalueprivate.h"
 
 struct _GtkColumnViewTitle
 {
@@ -52,6 +54,37 @@ struct _GtkColumnViewTitleClass
 
 G_DEFINE_TYPE (GtkColumnViewTitle, gtk_column_view_title, GTK_TYPE_WIDGET)
 
+static int
+get_number (GtkCssValue *value)
+{
+  double d = _gtk_css_number_value_get (value, 100);
+
+  if (d < 1)
+    return ceil (d);
+  else
+    return floor (d);
+}
+
+static int
+unadjust_width (GtkWidget *widget,
+                int        width)
+{
+  GtkCssStyle *style;
+  int widget_margins;
+  int css_extra;
+
+  style = gtk_css_node_get_style (gtk_widget_get_css_node (widget));
+  css_extra = get_number (style->size->margin_left) +
+              get_number (style->size->margin_right) +
+              get_number (style->border->border_left_width) +
+              get_number (style->border->border_right_width) +
+              get_number (style->size->padding_left) +
+              get_number (style->size->padding_right);
+  widget_margins = widget->priv->margin.left + widget->priv->margin.right;
+
+  return MAX (0, width - widget_margins - css_extra);
+}
+
 static void
 gtk_column_view_title_measure (GtkWidget      *widget,
                                GtkOrientation  orientation,
@@ -64,15 +97,18 @@ gtk_column_view_title_measure (GtkWidget      *widget,
   GtkColumnViewTitle *self = GTK_COLUMN_VIEW_TITLE (widget);
   GtkWidget *child = gtk_widget_get_first_child (widget);
   int fixed_width = gtk_column_view_column_get_fixed_width (self->column);
+  int unadj_width;
+
+  unadj_width = unadjust_width (widget, fixed_width);
 
   if (orientation == GTK_ORIENTATION_VERTICAL)
     {
       if (fixed_width > -1)
         {
           if (for_size == -1)
-            for_size = fixed_width;
+            for_size = unadj_width;
           else
-            for_size = MIN (for_size, fixed_width);
+            for_size = MIN (for_size, unadj_width);
         }
     }
 
@@ -82,7 +118,10 @@ gtk_column_view_title_measure (GtkWidget      *widget,
   if (orientation == GTK_ORIENTATION_HORIZONTAL)
     {
       if (fixed_width > -1)
-        *minimum = *natural = fixed_width;
+        {
+          *minimum = 0;
+          *natural = unadj_width;
+        }
     }
 }
 
@@ -96,7 +135,12 @@ gtk_column_view_title_size_allocate (GtkWidget *widget,
   GtkWidget *child = gtk_widget_get_first_child (widget);
 
   if (child)
-    gtk_widget_allocate (child, width, height, baseline, NULL);
+    {
+      if (gtk_column_view_column_get_fixed_width (self->column) > -1)
+        gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, height, NULL, &width, NULL, NULL);
+
+      gtk_widget_allocate (child, width, height, baseline, NULL);
+    }
 
   if (self->popup_menu)
     gtk_native_check_resize (GTK_NATIVE (self->popup_menu));